#include "hash.h"
#include <coding.h>

std::size_t minidb::Hash(const char *data, std::size_t n, std::size_t seed)
{
    const uint32_t m = 0xc6a4a793; // magic number
    const uint32_t r = 24;
    const char *limit = data + n;
    uint32_t h = seed ^ (m * n);
    while (data < limit)
    {
        uint32_t w = DecodeFixed32(data); // 1. 32位位旋转
        data += 4;
        h += w;         // 2. 累加循环后的4B
        h *= m;         // 3. 乘法扩散（低位↔高位）
        h ^= (h >> 16); // 4. 内部雪崩（高位→低位）
    }
    // 利用switch的 FALLTHROUGH_INTENDED 处理剩余字节，再进行一次乘法扩散+内部雪崩
    switch (limit - data)
    {
    case 3:
        h += static_cast<uint8_t>(data[2]) << 16;
    // FALLTHROUGH_INTENDED
    case 2:
        h += static_cast<uint8_t>(data[1]) << 8;
    // FALLTHROUGH_INTENDED
    case 1:
        h += static_cast<uint8_t>(data[0]);
        h *= m;
        h ^= (h >> r);
    default:
        break;
    }
    return h;
}